"""
知识库管理API端点
"""

from typing import List
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Form
from sqlalchemy.orm import Session
import os
import uuid
from pathlib import Path

from app.database import get_db
from app.services.knowledge_base_service import KnowledgeBaseService
from app.core import get_document_processor, get_rag_manager
from app.core.logging_config import get_logger
from app.schemas.knowledge_base import (
    KnowledgeBaseCreate, KnowledgeBaseUpdate, KnowledgeBaseResponse,
    DocumentResponse, KnowledgeBaseWithDocuments, KnowledgeBaseStats,
    DocumentUploadResponse
)

router = APIRouter()
logger = get_logger(__name__)
knowledge_base_service = KnowledgeBaseService()
document_processor = get_document_processor()()
rag_manager = get_rag_manager()()


@router.get("", response_model=List[KnowledgeBaseResponse])
async def get_knowledge_bases(
    skip: int = 0,
    limit: int = 100,
    active_only: bool = True,
    db: Session = Depends(get_db)
):
    """获取知识库列表"""
    try:
        filters = {}
        if active_only:
            filters["is_active"] = True
        
        knowledge_bases = knowledge_base_service.get_multi(
            db=db,
            skip=skip,
            limit=limit,
            filters=filters
        )
        
        return knowledge_bases
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取知识库列表失败: {str(e)}")


@router.get("/active", response_model=List[KnowledgeBaseResponse])
async def get_active_knowledge_bases(
    db: Session = Depends(get_db)
):
    """获取激活的知识库"""
    try:
        knowledge_bases = knowledge_base_service.get_active_knowledge_bases(db=db)
        return knowledge_bases
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取激活知识库失败: {str(e)}")


@router.get("/{knowledge_base_id}", response_model=KnowledgeBaseWithDocuments)
async def get_knowledge_base(
    knowledge_base_id: int,
    db: Session = Depends(get_db)
):
    """获取知识库详情"""
    try:
        knowledge_base = knowledge_base_service.get(db=db, id=knowledge_base_id)
        if not knowledge_base:
            raise HTTPException(status_code=404, detail="知识库不存在")
        
        documents = knowledge_base_service.get_knowledge_base_documents(
            db=db,
            knowledge_base_id=knowledge_base_id
        )
        
        knowledge_base.documents = documents
        return knowledge_base
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取知识库详情失败: {str(e)}")


@router.post("", response_model=KnowledgeBaseResponse)
async def create_knowledge_base(
    knowledge_base: KnowledgeBaseCreate,
    db: Session = Depends(get_db)
):
    """创建知识库"""
    try:
        new_knowledge_base = knowledge_base_service.create_knowledge_base(
            db=db,
            name=knowledge_base.name,
            description=knowledge_base.description,
            embedding_model=knowledge_base.embedding_model,
            chunk_size=knowledge_base.chunk_size,
            chunk_overlap=knowledge_base.chunk_overlap
        )
        
        # 创建向量集合
        rag_manager.create_collection(new_knowledge_base)
        
        return new_knowledge_base
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"创建知识库失败: {str(e)}")


@router.put("/{knowledge_base_id}", response_model=KnowledgeBaseResponse)
async def update_knowledge_base(
    knowledge_base_id: int,
    knowledge_base_update: KnowledgeBaseUpdate,
    db: Session = Depends(get_db)
):
    """更新知识库"""
    try:
        existing_knowledge_base = knowledge_base_service.get(db=db, id=knowledge_base_id)
        if not existing_knowledge_base:
            raise HTTPException(status_code=404, detail="知识库不存在")
        
        updated_knowledge_base = knowledge_base_service.update(
            db=db,
            db_obj=existing_knowledge_base,
            obj_in=knowledge_base_update
        )
        
        return updated_knowledge_base
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"更新知识库失败: {str(e)}")


@router.delete("/{knowledge_base_id}")
async def delete_knowledge_base(
    knowledge_base_id: int,
    db: Session = Depends(get_db)
):
    """删除知识库"""
    try:
        knowledge_base = knowledge_base_service.get(db=db, id=knowledge_base_id)
        if not knowledge_base:
            raise HTTPException(status_code=404, detail="知识库不存在")
        
        # 删除向量集合
        rag_manager.delete_collection(knowledge_base)
        
        # 删除知识库
        success = knowledge_base_service.delete(db=db, id=knowledge_base_id)
        if not success:
            raise HTTPException(status_code=500, detail="删除知识库失败")
        
        return {"message": "知识库删除成功"}
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"删除知识库失败: {str(e)}")


@router.get("/{knowledge_base_id}/documents", response_model=List[DocumentResponse])
async def get_knowledge_base_documents(
    knowledge_base_id: int,
    db: Session = Depends(get_db)
):
    """获取知识库文档列表"""
    try:
        documents = knowledge_base_service.get_knowledge_base_documents(
            db=db,
            knowledge_base_id=knowledge_base_id
        )
        
        # 手动构建响应数据，避免Pydantic验证问题
        result = []
        for doc in documents:
            # 处理metadata字段
            metadata = doc.document_metadata
            if metadata is None or not isinstance(metadata, dict):
                metadata = {}
            
            doc_data = {
                'id': doc.id,
                'knowledge_base_id': doc.knowledge_base_id,
                'filename': doc.filename,
                'original_filename': doc.original_filename,
                'file_path': doc.file_path,
                'file_size': doc.file_size,
                'file_type': doc.file_type,
                'content': doc.content,
                'metadata': metadata,
                'chunk_count': doc.chunk_count,
                'is_processed': doc.is_processed,
                'processing_status': doc.processing_status,
                'error_message': doc.error_message,
                'created_at': doc.created_at,
                'updated_at': doc.updated_at
            }
            result.append(DocumentResponse(**doc_data))
        
        return result
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取文档列表失败: {str(e)}")


@router.post("/{knowledge_base_id}/documents", response_model=DocumentUploadResponse)
async def upload_document(
    knowledge_base_id: int,
    file: UploadFile = File(...),
    db: Session = Depends(get_db)
):
    """上传文档到知识库"""
    try:
        # 检查知识库是否存在
        knowledge_base = knowledge_base_service.get(db=db, id=knowledge_base_id)
        if not knowledge_base:
            raise HTTPException(status_code=404, detail="知识库不存在")
        
        # 生成唯一文件名
        file_extension = Path(file.filename).suffix
        unique_filename = f"{uuid.uuid4().hex}{file_extension}"
        
        # 确保上传目录存在
        upload_dir = Path("uploads")
        upload_dir.mkdir(exist_ok=True)
        
        file_path = upload_dir / unique_filename
        
        # 保存文件
        with open(file_path, "wb") as buffer:
            content = await file.read()
            buffer.write(content)
        
        # 验证文件
        validation_result = document_processor.validate_file(str(file_path))
        if not validation_result["valid"]:
            os.remove(file_path)
            raise HTTPException(status_code=400, detail=validation_result["error"])
        
        # 处理文档
        documents = document_processor.process_file(
            str(file_path),
            metadata={"original_filename": file.filename}
        )
        
        # 添加到数据库
        document = knowledge_base_service.add_document(
            db=db,
            knowledge_base_id=knowledge_base_id,
            filename=unique_filename,
            original_filename=file.filename,
            file_path=str(file_path),
            file_size=len(content),
            file_type=file.content_type or "application/octet-stream",
            content=documents[0].page_content if documents else None
        )
        
        # 分割文档
        if documents:
            try:
                chunks = rag_manager.split_documents(
                    documents,
                    chunk_size=knowledge_base.chunk_size,
                    chunk_overlap=knowledge_base.chunk_overlap
                )
                
                # 添加到向量数据库
                success = rag_manager.add_documents(knowledge_base, chunks)
                if success:
                    # 更新文档状态
                    knowledge_base_service.update_document_processing_status(
                        db=db,
                        document_id=document.id,
                        status="completed",
                        chunk_count=len(chunks)
                    )
                    
                    # 更新知识库统计
                    knowledge_base.total_chunks += len(chunks)
                    db.commit()
                else:
                    knowledge_base_service.update_document_processing_status(
                        db=db,
                        document_id=document.id,
                        status="failed",
                        error_message="向量化失败"
                    )
            except Exception as e:
                knowledge_base_service.update_document_processing_status(
                    db=db,
                    document_id=document.id,
                    status="failed",
                    error_message=f"处理失败: {str(e)}"
                )
        
        return DocumentUploadResponse(
            document_id=document.id,
            filename=document.filename,
            file_size=document.file_size,
            processing_status=document.processing_status,
            message="文档上传成功"
        )
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"上传文档失败: {str(e)}")


@router.delete("/{knowledge_base_id}/documents/{document_id}")
async def delete_document(
    knowledge_base_id: int,
    document_id: int,
    db: Session = Depends(get_db)
):
    """删除文档"""
    try:
        # 检查知识库是否存在
        knowledge_base = knowledge_base_service.get(db=db, id=knowledge_base_id)
        if not knowledge_base:
            raise HTTPException(status_code=404, detail="知识库不存在")
        
        success = knowledge_base_service.delete_document(db=db, document_id=document_id)
        if not success:
            raise HTTPException(status_code=404, detail="文档不存在")
        
        return {"message": "文档删除成功"}
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"删除文档失败: {str(e)}")


@router.get("/{knowledge_base_id}/stats", response_model=KnowledgeBaseStats)
async def get_knowledge_base_stats(
    knowledge_base_id: int,
    db: Session = Depends(get_db)
):
    """获取知识库统计信息"""
    try:
        stats = knowledge_base_service.get_knowledge_base_stats(
            db=db,
            knowledge_base_id=knowledge_base_id
        )
        
        if not stats:
            raise HTTPException(status_code=404, detail="知识库不存在")
        
        return KnowledgeBaseStats(**stats)
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取知识库统计失败: {str(e)}")


@router.get("/{knowledge_base_id}/info")
async def get_knowledge_base_info(
    knowledge_base_id: int,
    db: Session = Depends(get_db)
):
    """获取知识库信息"""
    try:
        knowledge_base = knowledge_base_service.get(db=db, id=knowledge_base_id)
        if not knowledge_base:
            raise HTTPException(status_code=404, detail="知识库不存在")
        
        # 获取向量集合信息
        collection_info = rag_manager.get_collection_info(knowledge_base)
        
        return {
            "id": knowledge_base.id,
            "name": knowledge_base.name,
            "description": knowledge_base.description,
            "collection_name": knowledge_base.collection_name,
            "embedding_model": knowledge_base.embedding_model,
            "chunk_size": knowledge_base.chunk_size,
            "chunk_overlap": knowledge_base.chunk_overlap,
            "is_active": knowledge_base.is_active,
            "document_count": knowledge_base.document_count,
            "total_chunks": knowledge_base.total_chunks,
            "created_at": knowledge_base.created_at,
            "updated_at": knowledge_base.updated_at,
            "collection_info": collection_info
        }
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取知识库信息失败: {str(e)}")


@router.post("/{knowledge_base_id}/search")
async def search_knowledge_base(
    knowledge_base_id: int,
    query: str = Form(...),
    top_k: int = Form(default=5, le=20),
    db: Session = Depends(get_db)
):
    """搜索知识库"""
    try:
        knowledge_base = knowledge_base_service.get(db=db, id=knowledge_base_id)
        if not knowledge_base:
            raise HTTPException(status_code=404, detail="知识库不存在")
        
        # 检索相关文档
        documents = await rag_manager.retrieve_documents(
            knowledge_base, query, top_k
        )
        
        results = [
            {
                "content": doc.page_content,
                "metadata": doc.metadata,
                "distance": doc.metadata.get("distance", 0)
            }
            for doc in documents
        ]
        
        return {
            "query": query,
            "results": results,
            "total": len(results)
        }
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"搜索知识库失败: {str(e)}")
